package com.hoko.blur.processor;


import ohos.agp.components.Component;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Size;

import com.hoko.blur.anno.Mode;
import com.hoko.blur.anno.Scheme;
import com.hoko.blur.api.IBlurProcessor;
import com.hoko.blur.api.IBlurResultDispatcher;
import com.hoko.blur.task.AsyncBlurTask;
import com.hoko.blur.task.BitmapAsyncBlurTask;
import com.hoko.blur.task.BlurTaskManager;
import com.hoko.blur.task.ViewAsyncBlurTask;
import com.hoko.blur.util.BitmapUtil;
import com.hoko.blur.util.Preconditions;

import java.util.concurrent.Future;

/**
 * 模糊处理器
 *
 * @author
 * @date 2021/08/03
 */
public abstract class BlurProcessor implements IBlurProcessor {

    /**
     * 米半径
     */
    int mRadius;

    /**
     * m模式
     */
    @Mode
    int mMode;

    /**
     * m方案
     */
    @Scheme
    private int mScheme;

    /**
     * 米样因素
     */
    private float mSampleFactor;

    /**
     * m是力量复制
     */
    private boolean mIsForceCopy;

    /**
     * 米需要高档
     */
    private boolean mNeedUpscale;

    /**
     * m translatex
     */
    private int mTranslateX;
    /**
     * m translatey
     */
    private int mTranslateY;

    /**
     * m调度员
     */
    private IBlurResultDispatcher mDispatcher;

    /**
     * 模糊处理器
     *
     * @param builder 构建器
     */
    public BlurProcessor(HokoBlurBuild builder) {
        mMode = builder.mMode;
        mScheme = builder.mScheme;
        mRadius = builder.mRadius;
        mSampleFactor = builder.mSampleFactor;
        mIsForceCopy = builder.mIsForceCopy;
        mNeedUpscale = builder.mNeedUpscale;
        mTranslateX = builder.mTranslateX;
        mTranslateY = builder.mTranslateY;
        mDispatcher = builder.mDispatcher;
    }

    /**
     * 模式
     *
     * @param mode 模式
     */
    public void mode(@Mode int mode) {
        mMode = mode;
    }

    /**
     * 半径
     *
     * @param radius 半径
     */
    public void radius(int radius) {
        mRadius = radius;
    }

    /**
     * 样本的因素
     *
     * @param factor 因素
     */
    public void sampleFactor(float factor) {
        mSampleFactor = factor;
    }

    /**
     * 模式
     *
     * @return int
     */
    @Mode
    public int mode() {
        return mMode;
    }

    /**
     * 半径
     *
     * @return int
     */
    public int radius() {
        return mRadius;
    }

    /**
     * 样本的因素
     *
     * @return float
     */
    public float sampleFactor() {
        return mSampleFactor;
    }

    /**
     * 计划
     *
     * @return int
     */
    @Scheme
    public int scheme() {
        return mScheme;
    }

    /**
     * 力副本
     *
     * @return boolean
     */
    public boolean forceCopy() {
        return mIsForceCopy;
    }

    /**
     * 需要高档
     *
     * @return boolean
     */
    public boolean needUpscale() {
        return mNeedUpscale;
    }


    /**
     * translatex
     *
     * @return int
     */
    public int translateX() {
        return mTranslateX;
    }

    /**
     * translatey
     *
     * @return int
     */
    public int translateY() {
        return mTranslateY;
    }

    /**
     * 模糊
     *
     * @param bitmap 位图
     * @return {@link PixelMap}
     */
    @Override
    public PixelMap blur(PixelMap bitmap) {
        return doBlur(bitmap, true);
    }

    /**
     * 做模糊
     *
     * @param bitmap 位图
     * @param concurrent 并发
     * @return {@link PixelMap}
     */
    private PixelMap doBlur(PixelMap bitmap, boolean concurrent) {
        Preconditions.checkNotNull(bitmap, "bitmap == null");
        Preconditions.checkArgument(!bitmap.isReleased(), "You must input an unrecycled bitmap !");

        if (mRadius <= 0) {
            mRadius = 1;
        }

        if (mSampleFactor < 1.0f) {
            mSampleFactor = 1.0f;
        }

        PixelMap inBitmap = null;
        if (mIsForceCopy) {
            PixelMap.InitializationOptions opt = new PixelMap.InitializationOptions();
            opt.editable = true;
            opt.size = new Size(bitmap.getImageInfo().size.width, bitmap.getImageInfo().size.height);
            opt.pixelFormat = PixelFormat.ARGB_8888;
            inBitmap = PixelMap.create(bitmap, opt);
//            inBitmap = bitmap.copy(bitmap.getConfig(), true);
        } else {
            inBitmap = bitmap;
        }

        PixelMap transInBitmap = BitmapUtil.transformBitmap(inBitmap, translateX(), translateY());

        PixelMap scaledInBitmap = BitmapUtil.getScaledBitmap(transInBitmap, sampleFactor());

        PixelMap scaledOutBitmap = doInnerBlur(scaledInBitmap, concurrent);
        return mNeedUpscale ? BitmapUtil.getScaledBitmap(scaledOutBitmap, 1f / sampleFactor()) : scaledOutBitmap;
    }


    /**
     * 做内部模糊
     *
     * @param scaledBitmap 按比例缩小的位图
     * @param concurrent 并发
     * @return {@link PixelMap}
     */
    protected abstract PixelMap doInnerBlur(PixelMap scaledBitmap, boolean concurrent);

    /**
     * 模糊
     *
     * @param view 视图
     * @return {@link PixelMap}
     */
    @Override
    public PixelMap blur(Component view) {
        Preconditions.checkNotNull(view, "You must input a view !");
        PixelMap viewBitmap = BitmapUtil.getViewBitmap(view, translateX(), translateY(), sampleFactor());

        PixelMap scaledOutBitmap = doInnerBlur(viewBitmap, true);

        return mNeedUpscale ? BitmapUtil.getScaledBitmap(scaledOutBitmap, 1f / sampleFactor()) : scaledOutBitmap;
    }

    /**
     * 异步模糊
     *
     * @param bitmap 位图
     * @param callback 回调
     * @return {@link Future}
     */
    @Override
    public Future asyncBlur(PixelMap bitmap, AsyncBlurTask.Callback callback) {
        return BlurTaskManager.getInstance().submit(new BitmapAsyncBlurTask(this, bitmap, callback, mDispatcher));
    }

    /**
     * 异步模糊
     *
     * @param view 视图
     * @param callback 回调
     * @return {@link Future}
     */
    @Override
    public Future asyncBlur(Component view, AsyncBlurTask.Callback callback) {
        return BlurTaskManager.getInstance().submit(new ViewAsyncBlurTask(this, view, callback, mDispatcher));
    }

    /**
     * 免费的
     */
    protected void free() {

    }

}